#ifndef __POLL_SERVER_HPP__
#define __POLL_SERVER_HPP__

#include <iostream>
#include <string>
#include <poll.h>
#include <unistd.h>
#include "Log.hpp"
#include "Sock.hpp"

#define FD_NONE -1

class PollServer
{
private:
    static const int g_nfds=100;
    static const int g_timeout=3000;
public:
    PollServer(uint16_t port=8080,int nfds=g_nfds,int timeout=g_timeout)
        :_listenfd(-1)
        ,_nfds(nfds)
        ,_fds(new struct pollfd[_nfds])
        ,_timeout(timeout)
    {
        bool ret=_sock.CreateServer(port);
        if(ret==false)
        {
            ELOG("server create failed,%s",strerror(errno));
            exit(1);
        }
        _listenfd=_sock.Fd();
        for(int i=0;i<_nfds;i++)
        {
            _fds[i].fd=FD_NONE;
            _fds[i].events=_fds[i].revents=0;
        }
        _fds[0].fd=_listenfd;
        _fds[0].events=POLLIN;
        DLOG("server create success!!!");
    }

    void Accepter()
    {
        uint16_t port;
        std::string ip;
        int sockfd=_sock.Accept(&port,&ip);
        if(sockfd>0)
        {
            DLOG("get new link,sockfd:%d port:%d ip:%s",sockfd,port,ip.c_str());
            int i=0;
            for(;i<_nfds;i++)
            {
                if(_fds[i].fd==FD_NONE) break;
            }

            if(i==_nfds)
            {
                DLOG("_fds容量慢了，建议扩容！！！");
            }
            else
            {
                _fds[i].fd=sockfd;
                _fds[i].events=POLLIN;
                DLOG("添加进_fds成功!!!!");
            }
        }
        else
        {
            DLOG("server accept failed!!!");
        }
    }

    void Excepter(int sockfd)
    {
        for(int i=0;i<_nfds;i++)
        {
            if(_fds[i].fd==FD_NONE) continue;
            if(_fds[i].fd==sockfd)
            {
                _fds[i].fd=FD_NONE;
                _fds[i].events=_fds[i].revents=0;
                break;
            }
        }
    }

    void Recver(int sockfd)
    {
        char buffer[1024];
        bzero(buffer,sizeof(buffer));
        ssize_t s=recv(sockfd,buffer,sizeof(buffer)-1,0);
        if(s>0)
        {
            buffer[s]='\0';
            DLOG("client# %s",buffer);
            std::string messages="hello world#";
            messages+=buffer;
            send(sockfd,messages.c_str(),messages.size(),0);
        }
        else if(s==0)
        {
            DLOG("aside close,me too.....");
            Excepter(sockfd);
        }
        else
        {
            ELOG("server recv failed!!!");
            Excepter(sockfd);
        }
    }

    void LoopOnce()
    {
        int n=poll(_fds,_nfds,_timeout);
        if(n>0)
        {
            for(int i=0;i<_nfds;i++)
            {
                if(_fds[i].fd==FD_NONE) continue;
                //检测看是否就绪
                if(_fds[i].revents&POLLIN)
                {
                    if(_fds[i].fd==_listenfd)
                    {
                        Accepter();
                    }
                    else
                    {
                        Recver(_fds[i].fd);
                    }
                }
            }
        }
        else if(n==0)
        {
            DLOG("wait timeout.....");
        }
        else
        {
            DLOG("server poll failed!!!");
        }
    }


    void Start()
    {
        while(true)
        {
            LoopOnce();
        }
    }

    ~PollServer()
    {
        if(_listenfd>0) close(_listenfd);
        delete[] _fds;
    }

private:
    int _listenfd;
    Sock _sock;
    int _nfds;
    struct pollfd* _fds;
    int _timeout;
};

#endif